﻿using HalconDotNet;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Xml.Linq;

namespace halcon检测项目
{
    public partial class Form1 : Form
    {
        HObject image;
        HTuple windowID;
        Thread t1;
        //优化了Halcon中的数组
        HObject[] ImageArr =new HObject[8];
        bool t1_Stop = false;//线程的状态
        CSVApi csvapi   =new CSVApi();
        public Form1()
        {
            InitializeComponent();
        }
        #region 先把资源加载进来
        //注意：如果c#代码简单的情况下，首选手写c#
        private void LoadBateImage()
        {
            for (int i = 0; i < 8; i++)
            {
                HOperatorSet.ReadImage(out ImageArr[i], $"img/{i}.bmp");
            }
        }
        #endregion
        #region 加载窗体
        private void CreateHalconWindow()
        {
            //注意，这里没有hWindowControl控件了，变成了pictureBox
            HTuple winforms = this.pictureBox1.Handle;
            HOperatorSet.SetWindowAttr("background_color", "red");
            //这句代码决定了现在所有的试图在picture展示，交由windowID控制picture
            //winforms是付窗体
            HOperatorSet.OpenWindow(0, 0, this.pictureBox1.Width , this.pictureBox1.Height , winforms, "", "", out windowID);
        }
        #endregion
        #region 加载默认图片
        private void LoadImage() {
            HOperatorSet.ReadImage(out image,"img/0.bmp");
            HTuple Width =null, Height =null;
            HOperatorSet.GetImageSize(image, out Width, out Height);
            HOperatorSet.SetColor(windowID, "red");
            //追随图像大小,自适应
            HOperatorSet.SetPart(windowID,0,0, Height, Width);
            HOperatorSet.DispObj(image, windowID);
        }

        #endregion

        #region  加载配置环境
        private void Form1_Load(object sender, EventArgs e)
        {
            //读图
            LoadBateImage();
            //加载窗体
            CreateHalconWindow();
            //加载图像
            LoadImage();

            t1 = new Thread(new ThreadStart(PlayThread));
        }
        #endregion

        #region 开始测量
        private void button1_Click(object sender, EventArgs e)
        {
            //在分线程中加载图像
            //现成未开启，开启线程
            if (t1.ThreadState ==ThreadState.Unstarted)
            {
                t1.Start();
            }
            //如果线程停止或者线程为空
            if (t1.ThreadState ==ThreadState.Stopped || t1.ThreadState==ThreadState.Aborted)
            {
                //开启线程进行测量
                t1 = new Thread(new ThreadStart(PlayThread));
                t1.Start();
            }
        }
        private void PlayThread()
        {
            //测量，存储，一起执行
            //1.先获得测量半径
            int i = 0;
            t1_Stop = false;
            HTuple Width = null, Height = null;
            while (!t1_Stop)
            {
                HOperatorSet.DispObj(ImageArr[i], windowID);
                //注意每个图像大小不一样
                HOperatorSet.GetImageSize(ImageArr[i], out Width, out Height);
                HOperatorSet.SetPart(windowID,0,0, Height, Height);
                //渲染窗体
               double CriRad= ImageMeasure(ImageArr[i]);
              
                
                if (CriRad >311 && CriRad <313)
                {
                    Console.WriteLine("这是ok的");
                    //成功的图片存入成功图片的文件夹
                    UpdateView(i.ToString()+"_"+ CriRad.ToString()+"_"+"OK");
                    //以检测的时间作为图片的名称
                    string fileName =DateTime.Now.ToString("MM月dd日HH时mm分ss秒fff毫秒");
                    HOperatorSet.WriteImage(ImageArr[i], "bmp", 0, "ImageOK/" + fileName + ".bmp");

                    //成功的保存为csv文件
                    csvapi.SaveData("半径",CriRad.ToString());
                }
                else
                {
                    Console.WriteLine("这是NG的");
                    //成功的图片存入失败图片的文件夹
                    UpdateView(i.ToString() + "_" + CriRad.ToString() + "_" + "NG");
                    string fileName = DateTime.Now.ToString("MM月dd日HH时mm分ss秒fff毫秒");
                    HOperatorSet.WriteImage(ImageArr[i], "bmp", 0, "ImageNG/" + fileName + ".bmp");

                    //失败的存成log日志
                    csvapi.SaveLog("失败--半径不合格，数据为:"+ CriRad.ToString());
                }
                //刷新ui
                //拓展交互测量
                Thread.Sleep(1000);
                i++;
                if (i>=7)
                {
                    i = 0;
                }
            }

            //2.处理结果
        }
        #region 刷新ui的方法
        private void UpdateView(string result)
        {
            string[] status =result.Split('_');

            ListViewItem lt = new ListViewItem(status[0]);
            lt.SubItems.Add(status[1]);
            lt.SubItems.Add(status[2]);
            Console.WriteLine(this.listView1.Items);
            listView1.BeginInvoke(new Action<ListViewItem>((str1)=> {
             
                this.listView1.Items.Add(str1);
            }),lt);
        }
        #endregion
        //获取模型测量的结果
        private double ImageMeasure(HObject ho_ResultImage)
        {
            HObject ho_Image,  ho_ResultRegions = null;
            HObject ho_ResultConnectedRegions = null, ho_ResultSelectedRegions1 = null;
            HObject ho_ResultCircle = null, ho_ResultContour = null;

            HTuple hv_ImageFiles = new HTuple(), hv_Width = new HTuple();
            HTuple hv_Height = new HTuple(), hv_WindowHandle = new HTuple();
            HTuple hv_MetrologyHandle = new HTuple(), hv_NewRadius = new HTuple();
            HTuple hv_CirCleRadiusTolerance = new HTuple(), hv_Index = new HTuple();
            HTuple hv_ResultArea = new HTuple(), hv_ResultRow = new HTuple();
            HTuple hv_ResultColumn = new HTuple(), hv_MetrologyCircleIndice = new HTuple();
            HTuple hv_CircleRadiusResult = new HTuple();

            // Initialize local and output iconic variables 
            HOperatorSet.GenEmptyObj(out ho_Image);
            HOperatorSet.GenEmptyObj(out ho_ResultRegions);
            HOperatorSet.GenEmptyObj(out ho_ResultConnectedRegions);
            HOperatorSet.GenEmptyObj(out ho_ResultSelectedRegions1);
            HOperatorSet.GenEmptyObj(out ho_ResultCircle);
            HOperatorSet.GenEmptyObj(out ho_ResultContour);

            HOperatorSet.GetImageSize(ho_ResultImage, out hv_Width, out hv_Height);

            //开始测量
            //创建测量模型
            HOperatorSet.CreateMetrologyModel(out hv_MetrologyHandle);
            //设置测量模型的大小
            HOperatorSet.SetMetrologyModelImageSize(hv_MetrologyHandle, hv_Width, hv_Height);
            //定义圆的半径:注意，变得这个值
            hv_NewRadius = 324;
            //也可以配置其他的参数，例如测量对象的宽度允许范围
            hv_CirCleRadiusTolerance = 100;

            //特征提取
            //阈值分割，挑选出来配件部分
            ho_ResultRegions.Dispose();
            HOperatorSet.Threshold(ho_ResultImage, out ho_ResultRegions, 3, 60);
            //连通性
            ho_ResultConnectedRegions.Dispose();
            HOperatorSet.Connection(ho_ResultRegions, out ho_ResultConnectedRegions);
            //特征提取:用面积，和圆两个指标提取  area
            ho_ResultSelectedRegions1.Dispose();
            HOperatorSet.SelectShape(ho_ResultConnectedRegions, out ho_ResultSelectedRegions1,
         (new HTuple("area")).TupleConcat("roundness"), "and", (new HTuple(250000)).TupleConcat(
         0.9), (new HTuple(320000)).TupleConcat(1));
            //获取
            //hv_ResultArea.Dispose(); hv_ResultRow.Dispose(); hv_ResultColumn.Dispose();
            HOperatorSet.AreaCenter(ho_ResultSelectedRegions1, out hv_ResultArea, out hv_ResultRow,out hv_ResultColumn);

            HOperatorSet.SetColor(windowID, "green");
            HOperatorSet.SetDraw(windowID, "margin");
            HOperatorSet.DispObj(ho_ResultImage, windowID);

            //生成圆
            ho_ResultCircle.Dispose();
            HOperatorSet.GenCircle(out ho_ResultCircle, hv_ResultRow, hv_ResultColumn,
                hv_NewRadius);
            //把圆添加到模型中
            //hv_MetrologyCircleIndice.Dispose();
            HOperatorSet.AddMetrologyObjectCircleMeasure(hv_MetrologyHandle, hv_ResultRow,
                hv_ResultColumn, hv_NewRadius, hv_CirCleRadiusTolerance, 5, 1.5, 30, (new HTuple("measure_transition")).TupleConcat(
                "min_score"), (new HTuple("all")).TupleConcat(0.4), out hv_MetrologyCircleIndice);
            //测量并拟合集合形状
            HOperatorSet.ApplyMetrologyModel(ho_ResultImage, hv_MetrologyHandle);

            ho_ResultContour.Dispose();
            HOperatorSet.GetMetrologyObjectResultContour(out ho_ResultContour, hv_MetrologyHandle,
                "all", "all", 1.5);
            //在轮廓基础上获得此次测量的结果:第二个参数是每个图象的索引
            //hv_CircleRadiusResult.Dispose();
            HOperatorSet.GetMetrologyObjectResult(hv_MetrologyHandle, hv_MetrologyCircleIndice,
                "all", "result_type", "radius", out hv_CircleRadiusResult);
            //显示图像
            HOperatorSet.DispObj(ho_ResultImage, windowID);
            //显示测量轮廓
            HOperatorSet.DispObj(ho_ResultContour, windowID);
            HOperatorSet.SetTposition(windowID, 0, 0);
            HOperatorSet.WriteString(windowID, "圆的半径:" + hv_CircleRadiusResult);
            HOperatorSet.ClearMetrologyModel(hv_MetrologyHandle);
            ho_Image.Dispose();
            ho_ResultRegions.Dispose();
            ho_ResultSelectedRegions1.Dispose();
            ho_ResultConnectedRegions.Dispose();
            ho_ResultCircle.Dispose();
            ho_ResultContour.Dispose();
            //返回结果
            return hv_CircleRadiusResult;




        }
        #endregion

        private void button2_Click(object sender, EventArgs e)
        {
            t1_Stop = true;
        }

        private void button4_Click(object sender, EventArgs e)
        {
            this.Close();
            t1.Abort();
        }

        //交互测量
        private void button3_Click(object sender, EventArgs e)
        {
            HObject ho_Image, ho_Circle;
            HTuple hv_Row = null, hv_Column = null, hv_Radius = null;
            HOperatorSet.GenEmptyObj(out ho_Image);
            HOperatorSet.GenEmptyObj(out ho_Circle);
            HOperatorSet.SetColor(windowID, "green");
            HOperatorSet.SetDraw(windowID,"margin"); 
            HOperatorSet.DrawCircle(windowID, out hv_Row, out hv_Column, out hv_Radius);
            ho_Circle.Dispose();
            HOperatorSet.GenCircle(out ho_Circle, hv_Row, hv_Column, hv_Radius);
            HOperatorSet.DispObj(ho_Circle, windowID);
            ho_Image.Dispose();
            ho_Circle.Dispose();
        }
    }
}
